package cn.xx.user.service.impl;

import cn.xx.basic.constant.VerifactionCodeConstant;
import cn.xx.basic.exception.CustomException;
import cn.xx.basic.service.impl.BaseServiceImpl;
import cn.xx.basic.util.HttpClientUtils;
import cn.xx.basic.util.StrUtils;
import cn.xx.user.constant.WechatConstant;
import cn.xx.user.domain.LoginInfo;
import cn.xx.user.domain.User;
import cn.xx.user.domain.WechatUser;
import cn.xx.user.dto.UserDto;
import cn.xx.user.mapper.LoginInfoMapper;
import cn.xx.user.mapper.UserMapper;
import cn.xx.user.mapper.WechatUserMapper;
import cn.xx.user.service.IWechatService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import springfox.documentation.spring.web.json.Json;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WechatServiceImpl extends BaseServiceImpl<WechatUser> implements IWechatService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private LoginInfoMapper loginInfoMapper;

    @Autowired
    private WechatUserMapper wechatUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Map<String, Object> handleCallBackMethod(Map<String, String> map) {
        //获取授权码
        String code = map.get("code");
        //获取token的url地址
        String token_url = WechatConstant.TOKEN_URL.replace("APPID", WechatConstant.APPID)
                .replace("SECRET", WechatConstant.SECRET)
                .replace("CODE", code);
        //获取token的json字符串
        String jsonUrl = HttpClientUtils.httpGet(token_url);
        //把json字符串转为json对象
        JSONObject jsonObject = JSON.parseObject(jsonUrl);
        //获取json对象中指定的值（openid是微信用户唯一标志）
        String openid = jsonObject.getString("openid");
        //token的值
        String access_token = jsonObject.getString("access_token");
        System.out.println(openid+"  ----   "+access_token);
        //获取用户的url地址
        String user_url = WechatConstant.USER_URL
                .replace("ACCESS_TOKEN", access_token)
                .replace("OPENID", openid);

        //获取json字符串
        String userJsonUrl = HttpClientUtils.httpGet(user_url);
        //把json字符串转为json对象（获取用户json对象）
        jsonObject = JSON.parseObject(userJsonUrl);
        //通过openid查询微信用户对象
        WechatUser findwechatUser = wechatUserMapper.findOpenId(openid);
        //定义一个map集合，向门户网站响应后台数据
        HashMap<String, Object> resultMap = new HashMap<>();
        if(findwechatUser==null) {
            WechatUser wechatUser = new WechatUser();
            // 设置唯一标识的id
            wechatUser.setOpenid(openid);
            //昵称
            wechatUser.setNickname(jsonObject.getString("nickname"));
            //性别
            wechatUser.setSex(jsonObject.getInteger("sex"));
            //地址
            wechatUser.setAddress(jsonObject.getString("country")
                    +jsonObject.getString("province")
                    +jsonObject.getString("city"));
            //头像
            wechatUser.setHeadimgurl(jsonObject.getString("headimgurl"));
            // 保存用户信息到数据库
            wechatUserMapper.save(wechatUser);
            // 跳转到绑定界面(装openid，因为绑定账号，其实就是修改t_wxuser对应的数据)
            resultMap.put("openid", openid);// 只要后端返回了openid，就意味着我要跳转到绑定界面
            return resultMap;
        } else {
            LoginInfo loginInfo = findwechatUser.getLogininfo();
            if (loginInfo == null) {
                resultMap.put("openid", openid);// 只要后端返回了openid，就意味着我要跳转到绑定界面
                return resultMap;
            } else { // 两个表都有这个用户的数据  直接登录
                // 随机生成token 让前端拦截器放行
                String token = UUID.randomUUID().toString();
                // redis封装用户信息，30分钟过期 通过map封装返给前台
                redisTemplate.opsForValue().set("loginUser", loginInfo, 30, TimeUnit.MINUTES);
                resultMap.put("token", token);
                resultMap.put("loginUser", loginInfo);
                return resultMap;
            }
        }
    }

    @Override
    public Map<String, Object> binder(UserDto userDto) throws CustomException {
        // 校验数据
        checkData(userDto);
        // 通过手机号和登录类型查询登录信息表是否存在
        LoginInfo findLogin = loginInfoMapper.checkPhoneAndType(userDto.getPhone(), userDto.getType());
        if (findLogin == null) {
            // 创建登录信息
            findLogin = createLoginInfoByUserDto(userDto);
            //保存LoginInfo
            loginInfoMapper.save(findLogin);
            // 通过登录信息创建用户
            User user = createUserByLoginInfo(findLogin);
            // 保存用户
            userMapper.save(user);
            //绑定微信
            wechatUserMapper.binderWechatAndLoginInfo(findLogin.getId(), userDto.getOpenid());
        } else {
            //绑定微信
            wechatUserMapper.binderWechatAndLoginInfo(findLogin.getId(), userDto.getOpenid());
        }
        //直接登录(给redis设置值，给浏览器存储token和loginUser)
        HashMap<String, Object> resultMap = new HashMap<>();
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("loginUser", findLogin, 30, TimeUnit.MINUTES);
        resultMap.put("token", token);
        resultMap.put("loginUser", findLogin);
        return resultMap;
    }

    private User createUserByLoginInfo(LoginInfo loginInfo) {
        User user = new User();
        BeanUtils.copyProperties(loginInfo, user);
        user.setLoginInfo(loginInfo);
        return user;
    }


    private LoginInfo createLoginInfoByUserDto(UserDto userDto) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setPhone(userDto.getPhone());
        loginInfo.setType(userDto.getType());
        return loginInfo;
    }

    private void checkData(UserDto userDto) throws CustomException {
        if(StringUtils.isEmpty(userDto.getPhone())) {
            throw new CustomException("手机号为空");
        }
        if(StringUtils.isEmpty(userDto.getCode())) {
            throw new CustomException("验证码为空");
        }
        String codeValue = (String) redisTemplate.opsForValue().get(userDto.getPhone() + ":" + VerifactionCodeConstant.USER_CODE);
        // 获取前面一半的验证码
        String code = codeValue.split(":")[0];
        if (!code.equals(userDto.getCode())) {
            throw new CustomException("验证码错误");
        }

    }


}
